import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart';
import 'package:date_format/date_format.dart';
import 'package:path_provider/path_provider.dart';

class FileStore {
  String path;

  FileStore([this.path]) {
    // path ??= getApplicationDocumentsDirectory();
    // path ??= canonicalize('data/store.json');
    if (path == null) {
      _getPath().then((path) {
        path = path;
      });
    }
  }

  ///获取路径
  _getPath() async {
    var d = await getApplicationDocumentsDirectory();
    return d.path + 'data/store.json';
  }

  ///从文件中获取数据
  Future<List<dynamic>> getDataFromLocal() async {
    var f = File(await _getPath());
    if (await f.exists()) {
      var json = await f.readAsString();
      if (json == null) {
        return [];
      } else {
        return jsonDecode(json);
      }
    } else {
      await f.create(recursive: true);
      await f.writeAsString('[]');
      return [];
    }
  }

  ///更新文件所有内容
  Future<void> updateFile([List<Map<String, dynamic>> data]) async {
    var f = File(await _getPath());
    if (!await f.exists()) {
      await f.create(recursive: true);
    }
    await f.writeAsString(jsonEncode(data));
    return true;
  }
}

///存储类
class Store extends FileStore {
  static bool hasInited = false;
  static final List<InputStr> _cache = [];
  final Completer<bool> _then = Completer<bool>();
  Future<bool> promise;

  Store({String path, List<InputStr> json}) : super(path) {
    promise = _then.future;
    if (json != null && json.runtimeType == List) {
      if (Store.hasInited) {
        addData(json);
      } else {
        init().then((res) {
          addData(json);
        });
      }
    } else {
      init();
    }
  }

  ///添加数据的到数据库
  Future addData(List<InputStr> json) async {
    if (json != null) {
      if (Store.hasInited) {
        Store._cache.addAll(json);
      } else {
        await init();
        Store._cache.addAll(json);
      }
      await updateFile(toJson());
    }
    if (!_then.isCompleted) {
      _then.complete(true);
    }
  }

  Store.fromJson(List<Map<String, dynamic>> json) {
    if (json != null) {
      Store._cache.clear();
      List list = json.map((e) => InputStr.fromJson(e)).toList();
      Store(json: list);
    }
  }

  ///添加一条信息
  Future addOne(InputStr data) async {
    return addData([data]);
  }

  ///转化成json
  List<Map<String, dynamic>> toJson() {
    if (Store._cache.isNotEmpty) {
      return Store._cache
          .map((e) => {
                'text': e.text,
                'type': e.type.index,
                'date': e.date.millisecondsSinceEpoch
              })
          .toList();
    } else {
      return [];
    }
  }

  ///初始化
  Future init() async {
    if (promise.runtimeType == Future) return promise;
    if (!Store.hasInited) {
      super.path ??= await super._getPath(); //如果没有路径则获取
      var data = await getDataFromLocal();
      data ??= [];
      data.forEach((element) {
        Store._cache.add(InputStr.fromJson(element));
      });
      Store.hasInited = true;
    }
    if (!_then.isCompleted) {
      _then.complete(true);
    }
  }

  ///获取数据
  Future<InputStr> getAt(int index) async {
    if (!Store.hasInited) {
      await init();
    }
    return Future.value(Store._cache[index]);
  }

  ///获取所有数据
  Future<List<InputStr>> getAll() async {
    if (!Store.hasInited) {
      await init();
    }
    return Future.value(Store._cache);
  }

  ///删除
  void removeAt(int index) {
    Store._cache.removeAt(index);
    updateFile(toJson());
  }

  ///清除所有数据
  Future clear() async {
    Store._cache.clear();
    return updateFile();
  }
}

///输入类型
///result计算结果；expression表达式
enum inputType { expression, result }

///字符类
class InputStr {
  String text;
  inputType type;
  DateTime date;

  InputStr({@required this.text, @required this.type, this.date}) {
    date ??= DateTime.now();
  }

  ///fromJson构造函数
  InputStr.fromJson(Map<String, dynamic> json) {
    text = json['text'];
    type = inputType.values[json['type']];
    date = DateTime.fromMillisecondsSinceEpoch(json['date']);
  }

  ///转化成Map
  Map<String, dynamic> toJson() {
    return {
      'text': text,
      'type': type.index,
      'date': date.millisecondsSinceEpoch
    };
  }

  ///转化成日期字符串，例如 2020年12月5日
  String get dateStr {
    return formatDate(date, ['yyyy', '年', 'm', '月', 'd', '日']);
  }
}
